package eu.irreality.dai.gameplay.actions.interaction;

import eu.irreality.dai.gameplay.entities.AliveEntity;
import eu.irreality.dai.gameplay.events.GameEvent;
import eu.irreality.dai.gameplay.world.GameWorld;
import eu.irreality.dai.util.Direction;
import eu.irreality.dai.util.Position;
import eu.irreality.dai.util.exceptions.GameException;
import eu.irreality.dai.util.exceptions.InternalErrorException;
import eu.irreality.dai.world.gen.LevelGenerator;
import eu.irreality.dai.world.level.Level;

public class OpenAction extends InteractionAction
{

    /** Position of the door to be opened. */
    Position doorPos;

    /**
     * Do not use an action created in this way until setDirection has been
     * called with a concrete dir.
     * 
     * @param world
     * @param entity
     */
    public OpenAction(GameWorld world, AliveEntity entity)
    {
	super(world, entity);
	baseEnergyCost = 100;
    }

    public void setDirection(Direction dir)
    {
	this.doorPos = entity.getPosition().move(dir);
    }

    public OpenAction(GameWorld world, AliveEntity entity, Position doorPos)
    {
	this(world, entity);
	this.doorPos = doorPos;
    }

    public OpenAction(GameWorld world, AliveEntity entity, Direction dir)
    {
	this(world, entity, entity.getPosition().move(dir));
    }

    @Override
    public void execute() throws GameException, InternalErrorException
    {

	assert doorPos != null : "doorPos is null, perhaps missing call to setDirection() to parametrise action";

	int rowClosedDoor = doorPos.getRow();
	int colClosedDoor = doorPos.getCol();

	Level level = world.getActiveLevel(); // TODO this is wrong for
	// monsters!

	if (level.get(rowClosedDoor, colClosedDoor).contains(
		LevelGenerator.CLOSED_DOOR))
	{
	    world.notifyObservers(new GameEvent(level, doorPos, entity, null,
		    GameEvent.OPEN_DOOR));
	    level.remove(LevelGenerator.CLOSED_DOOR, rowClosedDoor,
		    colClosedDoor);
	    level.add(LevelGenerator.OPEN_DOOR, rowClosedDoor, colClosedDoor);
	} else
	{
	    world.notifyObservers(new GameEvent(level, doorPos, entity, null,
		    GameEvent.WHAT_DOOR));
	}

    }
}
